package net.sudot.chess.plugin;

import net.sudot.chess.business.model.PluginConfig;
import net.sudot.chess.business.service.PluginConfigService;
import net.sudot.chess.business.service.PluginService;
import net.sudot.chess.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 插件基础控制器
 *
 * @author tangjialin on 2018-03-18.
 */
@RestController
@RequestMapping("/admin/plugins")
public class PluginController {

    @Resource
    private PluginService pluginService;
    @Resource
    private PluginConfigService pluginConfigService;

    /**
     * 获取所有系统配置
     *
     * @return 返回所有系统配置项
     */
    @GetMapping
    public <Plugin extends BasePlugin> List<Plugin> list(String pluginType) {
        return pluginService.getPlugins(pluginType);
    }

    /**
     * 插件安装操作
     *
     * @param pluginId 插件的标识信息(插件的实现类在spring容器中的名称)
     */
    @PostMapping("/{pluginId}/install")
    public void install(@PathVariable String pluginId) {
        BasePlugin plugin = pluginService.getPlugin(pluginId);
        Assert.notNull(plugin, "插件不存在");
        if (!plugin.getIsInstalled()) {
            PluginConfig config = new PluginConfig();
            config.setPluginId(pluginId);
            config.setEnabled(false);
            config.setDisplayName(null);
            // 设置一个空map,不能为null,否则前端框架在绘制表单时,访问attributes里的属性会异常
            config.setAttributes(new HashMap<>(0));
            pluginConfigService.save(config);
            plugin.clearCache();
        }
    }

    /**
     * 插件卸载操作
     *
     * @param pluginId 插件的标识信息(插件的实现类在spring容器中的名称)
     */
    @PostMapping("/{pluginId}/uninstall")
    public void uninstall(@PathVariable String pluginId) {
        BasePlugin plugin = pluginService.getPlugin(pluginId);
        Assert.notNull(plugin, "插件不存在");
        if (plugin.getIsInstalled()) {
            pluginConfigService.deleteByPluginId(pluginId);
            plugin.clearCache();
        }
    }

    /**
     * 更新插件配置
     *
     * @param config 插件提交数据
     */
    @PutMapping
    public void update(@RequestBody PluginConfig config) {
        BasePlugin plugin = pluginService.getPlugin(config.getPluginId());
        Assert.notNull(plugin, "插件不存在");
        PluginConfig pluginConfig = plugin.getConfig();
        if (pluginConfig == null) { throw new BusinessException("请先安装此插件"); }

        Map<String, String> configAttributes = config.getAttributes();
        configAttributes = configAttributes == null ? new HashMap<>() : configAttributes;

        for (PluginAttributeConfig attributeConfig : plugin.getAttributeConfigs()) {
            String attributeCode = attributeConfig.getCode();
            String attributeValue = configAttributes.get(attributeCode);
            if (attributeConfig.isRequired() && StringUtils.isEmpty(attributeValue)) {
                throw new IllegalArgumentException(attributeConfig.getName() + "不能为空");
            }
            String validateRule = attributeConfig.getValidateRule();
            if (validateRule == null || validateRule.isEmpty()) { continue; }
            if (!attributeValue.matches(validateRule)) {
                throw new IllegalArgumentException("请输入正确的" + attributeConfig.getName());
            }
        }

        pluginConfig.setDisplayName(config.getDisplayName());
        pluginConfig.setEnabled(config.getEnabled() == null ? false : config.getEnabled());
        pluginConfig.setOrder(config.getOrder());
        pluginConfig.setAttributes(configAttributes);

        pluginConfigService.update(pluginConfig);
        plugin.clearCache();
    }
}